(function (fruit) {
    /**
     * @class fruit.ObservableCollection
     */
    fruit.define('fruit.ObservableCollection', fruit.Collection, {
        events: ['propertyChanged', 'collectionChanged'],
        methods: {
            clone: function () {
                return new fruit.ObservableCollection(this._data.slice());
            },
            /**
             * Add an item
             * @param item
             */
            add: function (item) {
                if (this.inherited(item)) {
                    this.notifyPropertyChanged('length');
                    this.notifyCollectionChanged({
                        action: 'add',
                        index: this.length(),
                        item: item
                    });
                }
            },
            /**
             * Remove an item
             * @param item
             */
            remove: function (item) {
                if (this.inherited(item)) {
                    this.notifyPropertyChanged('length');
                    this.notifyCollectionChanged({
                        action: 'remove',
                        index: this.length(),
                        item: item
                    });
                }
            },
            /**
             * Clear all items.
             */
            clear: function () {
                if (this.inherited()) {
                    this.notifyPropertyChanged('length');
                    this.notifyCollectionChanged({
                        action: 'reset'
                    });
                }
            },
            /**
             * Trigger a "propertyChanged" event.
             * @param name
             * @param newValue
             * @param oldValue
             */
            notifyPropertyChanged: function (name, newValue, oldValue) {
                this.fire('propertyChanged', {
                    property: name,
                    oldValue: oldValue !== undefined ? oldValue : undefined,
                    newValue: newValue !== undefined ? newValue : this.get(name)
                });
            },
            /**
             * Trigger a "collectionChanged" event.
             * @param data
             */
            notifyCollectionChanged: function (data) {
                this.fire('collectionChanged', data);
            }
        }
    });
})(fruit);
